package com.backend.modules.system.service.impl;

import com.backend.common.enums.DeptType;
import com.backend.common.enums.UserType;
import com.backend.common.exception.BusinessException;
import com.backend.modules.system.dto.StudentDTO;
import com.backend.modules.system.dto.StudentQueryDTO;
import com.backend.modules.system.entity.SysDepartment;
import com.backend.modules.system.entity.SysUser;
import com.backend.modules.system.repository.SysUserRepository;
import com.backend.modules.system.service.StudentService;
import com.backend.modules.system.service.SysDepartmentService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class StudentServiceImpl implements StudentService {

    private final SysUserRepository userRepository;
    private final SysDepartmentService departmentService;
    private final PasswordEncoder passwordEncoder;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(StudentDTO dto) {
        // 校验学号是否存在
        if (userRepository.existsByUserCode(dto.getUserCode())) {
            throw new BusinessException("学号已存在");
        }
        
        // 校验班级是否存在且类型是否正确
        SysDepartment department = departmentService.getById(dto.getDepartmentId());
        if (!DeptType.CLASS.getValue().equals(department.getType())) {
            throw new BusinessException("只能选择班级");
        }
        
        SysUser user = new SysUser();
        user.setUserCode(dto.getUserCode());
        user.setUsername(dto.getUserCode()); // 用户名默认为学号
        user.setPassword(passwordEncoder.encode(dto.getUserCode())); // 密码默认为学号
        user.setRealName(dto.getRealName());
        user.setPhone(dto.getPhone());
        user.setEmail(dto.getEmail());
        user.setUserType(UserType.STUDENT.getValue());
        user.setStatus(true);
        user.setDepartment(department);
        
        userRepository.save(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Long id, StudentDTO dto) {
        SysUser user = getById(id);
        
        // 校验班级是否存在且类型是否正确
        SysDepartment department = departmentService.getById(dto.getDepartmentId());
        if (!DeptType.CLASS.getValue().equals(department.getType())) {
            throw new BusinessException("只能选择班级");
        }
        
        user.setRealName(dto.getRealName());
        user.setPhone(dto.getPhone());
        user.setEmail(dto.getEmail());
        user.setDepartment(department);
        
        userRepository.save(user);
    }

    @Override
    public Page<SysUser> page(StudentQueryDTO query, Pageable pageable) {
        Specification<SysUser> spec = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 只查询学生
            predicates.add(criteriaBuilder.equal(root.get("userType"), UserType.STUDENT.getValue()));
            
            // 学号
            if (StringUtils.hasText(query.getUserCode())) {
                predicates.add(criteriaBuilder.like(root.get("userCode"), 
                        "%" + query.getUserCode() + "%"));
            }
            
            // 姓名
            if (StringUtils.hasText(query.getRealName())) {
                predicates.add(criteriaBuilder.like(root.get("realName"), 
                        "%" + query.getRealName() + "%"));
            }
            
            // 班级
            if (query.getDepartmentIds() != null && !query.getDepartmentIds().isEmpty()) {
                predicates.add(root.get("department").get("id").in(query.getDepartmentIds()));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        return userRepository.findAll(spec, pageable);
    }

    @Override
    public SysUser getById(Long id) {
        SysUser user = userRepository.findById(id)
                .orElseThrow(() -> new BusinessException("用户不存在"));
        
        // 校验是否为学生
        if (!UserType.STUDENT.getValue().equals(user.getUserType())) {
            throw new BusinessException("用户不是学生");
        }
        
        return user;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        SysUser user = getById(id);
        userRepository.delete(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(Long id, Boolean status) {
        SysUser user = getById(id);
        user.setStatus(status);
        userRepository.save(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPassword(Long id) {
        SysUser user = getById(id);
        // 重置密码为学号
        user.setPassword(passwordEncoder.encode(user.getUserCode()));
        userRepository.save(user);
    }
} 